//
// Constants
//

var  state_type_char = 0;    // State type for a character match
var state_type_split = 1;   // State type for a split
var state_type_match = 2;   // State type for the end state
var nfa_fragment_size = 2;  // The number of elements in a fragment
var nfa_state_size = 4;     // The number of elements in a state
var match_state_index = 0;  // The index of the matching state

//
// Globals
//

var re_index;               // A global (sigh) to keep track of where the parser is in converting from infix to postfix.

function re2post(re) {
    re_index = 0;
    return re2posthelper(re, 0, re.length);
}

function re2posthelper(re, paren, length) {

   // A recursive helper to do the actual conversion for re2post
    var buffer = "";
    var nalt = 0;   // Track the number of choices outstanding
    var natom = 0;  // Track the number of atoms on the stack
    var c, sub_buffer;

    for (; re_index < length; re_index++) {
        c = re.charAt(re_index);

        if (c == "(") {
            // Push the stack to handle a sub-expression
            if (natom > 1) {
                natom--;
                buffer = buffer + ".";
            }
            re_index++;
            sub_buffer = re2posthelper(re, paren + 1, length);
            if (sub_buffer == null) {
                return null;
            } else {
                buffer = buffer + sub_buffer;
                natom++;
            }

        } else if (c == "|") {
            // Choice... concatenate all pending atoms and increment our choices
            if (natom == 0) {
                return null;
            } else {
                while (--natom > 0) {
                    buffer = buffer + ".";
                }
                nalt++;
            }

        } else if (c == ")") {
            // Pop the stack at the end of a sub expression
            if ((paren <= 0) || (natom == 0)) {
                return null;
            }

            while (--natom > 0) {
                // Concatenate all the atoms on the stack
                buffer = buffer + ".";
            }
            for (; nalt > 0; nalt--) {
                // Tack on all the choice symbols for all the choices outstanding
                buffer = buffer + "|";
            }

            return buffer;

        } else if ((c == "*") || (c == "+") || (c == "?")) {
            // Basic operators... just add them
            if (natom == 0) {
                return NULL_KEY;
            } else {
                buffer = buffer + c;
            }

        } else {
            // Simple characters... just add them and increment the number of atoms
            if (natom > 1) {
                --natom;
                buffer = buffer + ".";
            }
            buffer = buffer + c;
            natom++;
        }
    }

    while (--natom > 0) {
        // Concatenate all the atoms on the stack
        buffer = buffer + ".";
    }
    for (; nalt > 0; nalt--) {
        // Tack on all the choice symbols for all the choices outstanding
        buffer = buffer + "|";
    }

    return buffer;

}
